<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">






  
  
  <link rel="stylesheet" media="all" href="/lib/Han/dist/han.min.css?v=3.3">




<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/images/favicon.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon.png?v=5.1.4">


  <link rel="mask-icon" href="/images/favicon.png?v=5.1.4" color="#222">





  <meta name="keywords" content="Linux," />





  <link rel="alternate" href="/atom.xml" title="平步青云win" type="application/atom+xml" />






<meta name="description" content="Linux内核介绍，以及内核中C语言的特点！">
<meta name="keywords" content="Linux">
<meta property="og:type" content="article">
<meta property="og:title" content="Linux内核分析">
<meta property="og:url" content="https://zxpgo.github.io/2019/06/11/Linux内核阅读问题/index.html">
<meta property="og:site_name" content="平步青云win">
<meta property="og:description" content="Linux内核介绍，以及内核中C语言的特点！">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2019-06-20T14:39:10.453Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Linux内核分析">
<meta name="twitter:description" content="Linux内核介绍，以及内核中C语言的特点！">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"right","display":"post","offset":10,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: 'PAO8LM7QB1',
      apiKey: '',
      indexName: 'Blog',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://zxpgo.github.io/2019/06/11/Linux内核阅读问题/"/>





  <title>Linux内核分析 | 平步青云win</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?7a4517a3ce6d7c50203655d056f01ac3";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-right page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">平步青云win</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <h1 class="site-subtitle" itemprop="description"></h1>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-随笔">
          <a href="/sui" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-question-circle"></i> <br />
            
            随笔
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
			
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br />
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off"
             placeholder="搜索..." spellcheck="false"
             type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://zxpgo.github.io/2019/06/11/Linux内核阅读问题/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="zxp">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="平步青云win">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">Linux内核分析</h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-06-11T13:44:14+08:00">
                2019-06-11
              </time>
            

            

            
          </span>

          

          
            
          

          
          
             <span id="/2019/06/11/Linux内核阅读问题/" class="leancloud_visitors" data-flag-title="Linux内核分析">
               <span class="post-meta-divider">|</span>
               <span class="post-meta-item-icon">
                 <i class="fa fa-eye"></i>
               </span>
               
                 <span class="post-meta-item-text">阅读次数&#58;</span>
               
                 <span class="leancloud-visitors-count"></span>
             </span>
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body han-init-context" itemprop="articleBody">

      
      

      
        <p>Linux内核介绍，以及内核中C语言的特点！<a id="more"></a></p>
<h2 id="内核开发特点"><a href="#内核开发特点" class="headerlink" title="内核开发特点"></a>内核开发特点</h2><h3 id="无libc库或无标准头文件"><a href="#无libc库或无标准头文件" class="headerlink" title="无libc库或无标准头文件"></a>无libc库或无标准头文件</h3><p>Linux内核无法使用C语言的库函数，但是Linux内核实现了这些库函数，实现的文件(即.c文件)包含在lib目录下，头文件(即.h文件)在include\linux目录下。</p>
<p>基本的头文件位于include\linux目录下；体系结构相关的头文件位于内核源代码数的arch/<architecture>/include/asm目录下。比如如果编译的是x86体系结构，则体系结构相关的头文件就是arch/x86/include/asm</architecture></p>
<p>使用的时候包含如下头文件：</p>
<pre><code>//包含基本头文件
#include &lt;linux/string.h&gt;
//包含体系结构相关的头文件
#include &lt;asm/ioctl.h&gt;
</code></pre><p>内核肯定无法调用printf，但是其提供了printk函数，几乎与printf()相同。printk()函数负责把格式化好的字符串拷贝到内核日志缓冲区上，这样syslog程序就可以通过读取该缓冲区来获取内核信息。printk()用法：</p>
<pre><code>printk(&quot;Hello world! A string: &apos;%s&apos; and an integer: &apos;%d&apos;\n&quot;, str ,i);
</code></pre><p>printk()与printf()的一个区别在于，printk()允许你通过一个标志来设置优先级。syslog会根据这个优先级标志来决定在什么地方显示这条系统信息。下面是一个车使用这种优先级标志的例子：</p>
<pre><code>printk(KERN_ERR &quot;This is an error!\n&quot;);
</code></pre><p>注意:KERN_ERR和要打印的消息之间没有逗号。优先级标志是预处理程序定义的一个描述性字符串，在编译时优先级标志与要打印的信息绑定在一起处理。</p>
<h3 id="GNU-C"><a href="#GNU-C" class="headerlink" title="GNU C"></a>GNU C</h3><p>Linux使用的是GNU C。</p>
<p>C语言扩展：</p>
<ul>
<li>inline函数：函数会在他所调用的位置上展开，这样会消除函数调用和返回所带来的开销。代价是代码会变长，占用更多的内存空间。所以经常把对时间要求比较高，而本身长度比较短的函数定义为内敛函数。</li>
</ul>
<p>定义内敛函数时，需要使用static作为关键字，并且用inline限定他。比如：</p>
<pre><code>static inline void wolf(unsigned long tail_size)
{ ...}
</code></pre><p>使用static限制，编译时不会为内联函数单独建立一个函数体。</p>
<p>为了安全险，优先使用内联函数，而不是复杂的宏</p>
<ul>
<li>内联汇编</li>
</ul>
<p>C函数中可以嵌入汇编指令。</p>
<p>通常使用asm()指令来嵌入汇编代码。</p>
<p>在偏近体系结构的底层或对执行时间要求严格的地方，一般使用汇编语言；而内核的其他部分使用C语言。</p>
<ul>
<li>分支声明</li>
</ul>
<p>对于条件选择语句，gcc内建了一条指令用于优化，在一个条件经常出现，或者该条件很少出现的时候，编译器可以根据这条指令对条件分支选择进行优化。内核把这条指令封装成了宏，比如likely()和unlikely()，这样使用起来比较方便。</p>
<p>例如，普通的分支声明：</p>
<pre><code>if (error) {...}
</code></pre><p>如果想要把这个选择标记成绝少发生的分支：</p>
<pre><code>if(unlikely(error)) {...}
</code></pre><p>相反，如果我们想把一个分支标记成通常为真的选择：</p>
<pre><code>if(likely(error)) {...}
</code></pre><h3 id="内有内存保护机制"><a href="#内有内存保护机制" class="headerlink" title="内有内存保护机制"></a>内有内存保护机制</h3><p>如果一个用户程序视图进行一次非法的内存访问，内核就会出现错误，发送SIGSEGV信号，并结束进程。</p>
<p>如果是内核自己非法访问了内存，那后果加很难控制了。内核中发生的内存错误会导致oops，这是内存中出现的最常见的一类错误。在内核中，不应该取访问非法的内存地址，引用控制住，否则会死掉，却根本不告诉你。</p>
<p>内核中的内存都不分页。即，你用掉一个字节，物理内存就减少一个字节。</p>
<h3 id="不要轻易在内核中使用浮点数"><a href="#不要轻易在内核中使用浮点数" class="headerlink" title="不要轻易在内核中使用浮点数"></a>不要轻易在内核中使用浮点数</h3><p>用户空间的进程内进行浮点数操作的时候，内核会完成从整数操作到浮点数操作的模式转换。</p>
<p>而内核空间并不能完美地支持浮点操作，因为它本身不能陷入。在内核中使用浮点数，除了要人工保存和恢复浮点寄存器，还有其他一些琐碎的事情要做。</p>
<p>总之，在内核，不要进行浮点数操作。</p>
<h3 id="容积小而固定的栈"><a href="#容积小而固定的栈" class="headerlink" title="容积小而固定的栈"></a>容积小而固定的栈</h3><p>用户空间的成协商可以从栈上分配大量的空间来存放变量，甚至巨大的结构体和数组等。这是因为用户空间的栈本身很大，而且还可以动态增长。</p>
<p>而内核栈的准确大小随体系结构而变。内核栈的大小是两页，即32位机内核栈是8KB，而64位机是16KB，这是固定不变的。每个处理器都有自己的栈。</p>
<h3 id="同步和并发"><a href="#同步和并发" class="headerlink" title="同步和并发"></a>同步和并发</h3><p>内核很容器产生竞争条件。和单线程的用户空间程序不同，内核的特性要求能够并发地访问共享数据，这就要求同步机制以保证不出现竞争条件。</p>
<h3 id="可移植性的重要性"><a href="#可移植性的重要性" class="headerlink" title="可移植性的重要性"></a>可移植性的重要性</h3><p>用户空间的成协商不太注意移植问题，然而Linux却是一个可移植的操作系统，并且一直保持这种特点。即，大部分C代码应该与体系结构无关。</p>
<h2 id="2-进程管理"><a href="#2-进程管理" class="headerlink" title="2 进程管理"></a>2 进程管理</h2><h3 id="2-1-进程"><a href="#2-1-进程" class="headerlink" title="2.1 进程"></a>2.1 进程</h3><p>进程是出于执行期的程序以及相关的资源的总称。存在多个进程执行的是同一个程序，并且多个并存的进程还可以共享地址空间等资源。</p>
<p>线程是在进程中活动的对象。在Linux而言，线程只不过是一种特殊的进程罢了。</p>
<p>在现代操作系统中，进程提供了两种虚拟机制：虚拟处理器和虚拟内存。即多个进程在分享一个处理器，但虚拟处理器给进程一种假象，让这些进程觉得自己在独享处理器。</p>
<p>Linux中，通常是调用fork()通过复制一个现有的进程来创建一个全新的进程。调用fork()的进程称为父进程，新产生的进程称为子进程。在调用结束时，在返回点这个相同位置上，父进程恢复执行，子进程开始执行。</p>
<p>exec()这组函数可以创建新的地址空间，并把新的程序载入其中。</p>
<p>在linux内核中，fork()实际上是由clone()系统调用实现的。</p>
<p>exit()系统调用退出执行。这个函数会终结进程并将其占用的资源释放掉。</p>
<p>父进程可以通过wait4()系统调用查询子进程是否终结。</p>
<h3 id="2-2-进程描述符及任务结构"><a href="#2-2-进程描述符及任务结构" class="headerlink" title="2.2 进程描述符及任务结构"></a>2.2 进程描述符及任务结构</h3><p>内核把进程的列表存放在叫做任务队列的双向循环列表中。链表中的每一项都是类型为task_struct，称为进程描述符的结构，该结构定义在&lt;linux/sched.h&gt;文件中。进程描述符中包含一个具体进程的所有信息。</p>
<p>task_sturct相对比较大。这是由于该结构内包含了内核管理一个进程所需的所有信息。进程描述符中包含的数据能完整地描述一个正在执行的程序：它打开的文件，进程的地址空间，挂起的信号，进程的状态等等。</p>
<p>Linux通过slab分配器分配<code>task_struct</code>结构，这样能达到对象复用和缓存着色的目的。由于现在用slab分配器动态生成<code>task_struct</code>，所以只需在栈底或栈顶创建一个新的结构<code>struct thread_info</code>。<code>thread_info</code>头文件在arch\x86\include\asm目录下。</p>
<p>内核通过一个唯一的进程标识值或PID来标识每个进程。PID是一个数，标识为<code>pid_t</code>隐含类型，实际上就是一个int类型。PID的最大值默认设置为32768（short int的最大值），尽管这个值可以增加到到达400万（在&lt;linux/threads.h&gt;中所定义的PID最大值的限制）。内核把每个进程的PID存放在它们各自的进程描述符中。</p>
<p>进程描述符中的state描述了进程的当前状态：</p>
<ul>
<li>运行（TASK_RUNNING）</li>
<li>可中断（TASK_INTERRUPTIBLE）：进程正在睡眠（即它被阻塞）</li>
<li>不可中断（TASK_UNINTERRUPTIBLE）</li>
<li><code>__TASK_TRACED</code>：被其他进程跟踪的进程</li>
<li>停止（<code>__TAS_STOPPED</code>）</li>
</ul>
<p>设置当前进程状态：</p>
<p><code>set_task_state(task, state)</code>函数将制定的进程设置为指定的状态。</p>
<p><code>set_current_state(state)</code>和<code>set_task_state(current, state)</code>含义是等同的。</p>
<p>所有进程都是PID为1的init进程的后代。内核在系统启动的最后阶段启动init进程。</p>
<p>系统中的每一个进程必有一个父进程，每个进程也可以拥有零个或多个子进程。</p>
<p>每个task_struct都包含一个指向其父进程<code>tast_sturct</code>，叫做parent的指针，还包含一个称为children的子进程链表。</p>
<h3 id="2-3-进程的创建"><a href="#2-3-进程的创建" class="headerlink" title="2.3 进程的创建"></a>2.3 进程的创建</h3><p>首先，fork()通过拷贝当前进程创建一个子进程。子进程与父进程的区别仅仅在于PID和资源的统计量。exec()函数负责读取可执行文件并将其载入地址空间开始运行。这两个函数组合在一起使用的效果跟其他操作系统使用的单一函数一样。</p>
<p>写时拷贝</p>
<p>传统的fork()系统调用直接把所有的资源复制到新创建的进程。这种实现过于简单并且效率低下。Linux的fork()使用写时拷贝页实现。写时拷贝是一个可以推迟甚至避免拷贝数据的技术。内核此时并不复制整个进程地址空间，而是让父进程和子进程共享同一个拷贝。</p>
<p>Linux通过clone()系统调用使用fork()。然后又clone()调用do_fork()。<code>do_fork()</code>再调用<code>_do_fork()</code>。</p>
<p><code>_do_fork()</code>完成了创建中的大部分工作，它的定义在kernel/forK.c文件中。该函数调用<code>copy_process()</code>函数，然后让进程开始运行。</p>
<p><code>copy_process()</code>函数完成的工作：</p>
<ul>
<li>调用<code>dup_task_struct()</code>为新进程创建一个内核栈、<code>thread_info</code>结构和<code>task_struct</code>，这些值与当前进程的值相同。</li>
<li>检查并确保新创建这个子进程后，当前用户所拥有的进程数目没有超过它分配的资源限制。</li>
<li>子进程着手使自己与父进程区别开来。进程描述符内的许多成员都要被清0或设为初始值。</li>
<li>子进程的状态被设置为TASK_UNITERRUPTIBLE，以保证它不会投入运行。</li>
<li>调用<code>copy_flags()</code>以更新<code>task_sturct</code>的flags成员，表明进程是否拥有超级用户权限的<code>PF_SUPERPRIV</code>标志被清0，表明进程还没被调用exce()函数的<code>PF_FORKNOEXEC</code>标志被设置。</li>
<li>调用<code>alloc_pid()</code>为新进程分配一个有效的PID。</li>
<li>根据创建给clone()的参数标志，<code>copy_process()</code>拷贝或共享打开的文件、文件系统信息、信号处理函数、进程地址空间和命名空间。</li>
<li>最后，copy_process()做扫尾工作并返回一个指向子进程的指针。</li>
</ul>
<p>除了不拷贝父进程的页表项外，vfork()系统调用和fork()的功能相同。由于fork()有了写时拷贝页表现，那么vfork()就彻底没用了。</p>
<h3 id="2-4-线程再Linux中的实现"><a href="#2-4-线程再Linux中的实现" class="headerlink" title="2.4 线程再Linux中的实现"></a>2.4 线程再Linux中的实现</h3><p>线程机制是现代编程技术中常用的一种抽象概念。该机制提供了在同一程序内共享内存地址空间运行的一组线程。这些线程还可以共享打开的文件和其他资源。</p>
<p>Linux实现线程的机制非常独特。从内核的角度来看，它并没有线程这个概念。Linux把所有的线程当作进程来实现。线程仅仅被视为一个与其他进程共享某些资源的进程，每一个线程都拥有唯一隶属于自己的<code>task_struct</code>，所以在内核中，它看起来就是一个普通的进程。</p>
<p>上述的线程机制与Windoes等系统的实现差异非常大。这些系统在内核提供了专门支持线程的机制。这些系统常常把线程称作轻量级进程。</p>
<p>在其他的系统中，相较于重量级的进程，线程被抽象成为一种耗费较少资源，运行迅速的执行单元。而对于Linux，它只是一种进程间共享资源的手段（Linux的进程本身就够轻量级了）。</p>
<p>创建线程：</p>
<p>线程的创建和普通进程的创建类似，只不过调用clone()的时候需要传递一些参数标志了指向需要共享的资源。</p>
<p>内核线程：</p>
<p>内核线程只能由其他内核线程创建。内核是通过从kthreadd内核进程中衍生出所有新的内核线程来自动处理这一点的。在&lt;linux/kthread.h&gt;中申明有接口。于是，从现有内核线程中创建一个新的内核线程的方法如下：</p>
<pre><code>struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
                       void *data,
                       int node,
                       const char namefmt[], ...);
</code></pre><p>内核线程被创建后，如果不通过调用<code>wake_up_process()</code>明确唤醒它，它不会主动运行。创建一个并让他运行起来，可以通过调用<code>thread_run()</code>来到达，这个函数以宏实现，只是简单的调用<code>kthread_create()</code>和<code>wake_up_process()</code>。</p>
<h3 id="2-5-进程终结"><a href="#2-5-进程终结" class="headerlink" title="2.5 进程终结"></a>2.5 进程终结</h3><p>当进程终结时，内核必须释放它所占有的资源并把这一不幸告知父进程。</p>
<p>进程的终结，该任务大部分要靠<code>do_exit()</code>来完成（定义在kernel/exit.c）。</p>
<p>调用<code>do_exit()</code>之后，线程已经僵死不能再运行，但是系统还保留了它的进程描述符。这样可以让系统有办法在子进程终结后仍能获得它的信息。</p>
<p>如果父进程在子进程之前退出，必须有机制来保证子进程能找到一个新的父进程，否则这些成为孤儿的进程辉在退出时永远处于僵死状态，白白地消耗内存。</p>
<p>解决办法是给子进程在当前线程组内找一个线程作为父进程，如果不行，就让init做它们的父进程。寻找父进程的的函数<code>find_new_reaper()</code>。</p>
<h2 id="13-虚拟文件系统"><a href="#13-虚拟文件系统" class="headerlink" title="13 虚拟文件系统"></a>13 虚拟文件系统</h2><p>虚拟文件系统，简称VFS，作为内核自系统，为用户空间程序提供了文件和文件系统相关的接口。系统中所有文件系统不但依赖VFS共存，而且依靠VFS系统协同工作。通过虚拟文件系统，程序可以利用标准的Unix系统调用对不同的文件系统，甚至不同介质上的文件系统进行读写操作。</p>
<p>VFS使得用户可以直接使用open(),read()和write()这样的系统调用而无需考虑具体文件系统和实际物理介质。</p>
<p>之所以可以使用这种通用接口对所有类型的文件系统进行操作，是因为内核在它的底层文件系统接口上建立一个抽象层。该抽象层使Linux能够支持各种文件系统，即便是他们在功能和行为上存在很大差别。为了支持多文件系统，VFS提供了一个通用文件系统模型，该模型囊括了人任何文件系统的常用功能集和行为。</p>
<p>VFS抽象层之所能衔接各种各样的文件系统，是因为它定义了所有文件系统都支持的、基本的、概念上的接口和数据结构。</p>
<p>在内核中，除了文件系统本身外，其他部分并不需要了解文件系统的内部细节。比如一个简单的用户空间程序执行如下操作：</p>
<pre><code>ret = write(fd, buf, len);
</code></pre><p>该系统调用将buf指针指向的长度为len字节的数据写入文件描述符fd对应的文件的当前位置。</p>
<p>这个系统调用首先被一个通用系统调用<code>sys_write()</code>处理，<code>sys_write()</code>函数要找到fd所在的文件系统实际给出的是哪个操作，然后再执行该操作。</p>
<p>Unix文件系统：</p>
<p>Unix使用了四种和文件系统相关的传统抽象概念：文件、目录项、索引节点和安装点（mount point）。</p>
<p>目录属于普通文件，它记录再其目录下的所有文件。</p>
<p>文件相关信息，包括访问控制权限、大小、拥有者、创建事件等信息，有时被称为文件的元数据，被存储再一个单独的数据结构中，该结构被称为索引节点（inode），其实是index node的缩写。</p>
<p>超级快是一种包含文件系统信息的数据结构，包含文件系统的控制信息。</p>
<p>FAT或NTFS这样的非Unix风格的文件系统，需要经过封装，提供一个符合这些概念的界面，才可以在Linux上工作。比如，即使一个文件系统不支持索引节点，它也必须在内存中装配索引节点结构体。</p>
<h3 id="VFS对象及其数据结构"><a href="#VFS对象及其数据结构" class="headerlink" title="VFS对象及其数据结构"></a>VFS对象及其数据结构</h3><p>VFS其实采用的是面向对象的设计思路，使用一组数据结构来代表通用文件对象。这些数据结构类似于对象，因为内核纯粹使用C代码实现，没有直接利用面向对象的语言，所以内核中的数据结构都是用C语言的结构体实现，而这些结构体包含数据的同时也包含操作这些数据的函数指针，其中的操作函数由具体的文件系统实现。</p>
<p>VFS中由4个主要的对象类型：</p>
<ul>
<li>超级快对象：它代表一个具体的已安装文件系统；</li>
<li>索引节点对象：它代表一个具体文件；</li>
<li>目录项对象：它代表一个车目录项，是路径的一个组成部分；</li>
<li>文件对象：它代表有进程打开的文件。</li>
</ul>
<p>因为VFS将目录作为一个文件来处理，所以不存在目录对象。目录项代表的是一个路径中的一部分，它可能包括一个普通文件。目录项不同于目录，但目录却是另一种形式的文件。</p>
<p>每个主要对象中都包含一个操作对象，这些操作对象描述了内核针对主要对象可以使用的方法：</p>
<ul>
<li><code>super_operations</code>对象，其中包含内核针对特定文件系统所能调用的方法，比如<code>write_inode()</code>和<code>sync_fs()</code>等方法。</li>
<li><code>inode_operations</code>对象，其中包含书内核针对特定文件所能调用的方法，比如create()方法和link()等方法。</li>
<li><code>dentry_operations</code>对象，其中包含内核针对特定目录所能调用的方法，比如<code>d_compare()</code>和<code>d_delete()</code>等方法。</li>
<li><code>file_operations</code>对象，其中包括进程针对已打开文件所能调用的方法，比如read()和write()等方法。</li>
</ul>
<p>操作对象作为一个结构体实现指针来实现，此结构体中包含指向操作其父对象的函数指针。对于其中许多方法来说，可以继承使用VFS提供的通用函数，如果通用函数提供的基本功能无法满足需要，那么就必须使用实际文件系统的独有方法填充这些函数指针，使其指向文件系统实例。</p>
<p>VFS使用了大量的结构体对象，远不止上面四种主要的对象。比如，每个注册的文件系统都由<code>file_system_type</code>结构体来表示，它描述了文件系统及其性能；另外，每一个安装点也都用vfsmount结构体表示，它包含的是安装点的相关信息，比如位置和安装标志等。</p>
<p><code>fs_struct</code>结构体和file结构体分别描述了文件系统以及和进程相关的文件。</p>
<p>超级块对象由<code>super_block</code>结构体表示，在文件&lt;linux/fs.h&gt;中，创建、管理和撤销超级块对象的代码文娱文件fs/super.c中。超级块对象通过调用<code>alloc_super()</code>函数创建并初始化。在文件系统安装时，文件系统会调用该函数以便从磁盘读取文件系统超级块，并且将其信息填充到内存中的超级块对象中。</p>
<p>超级块对象中最重要的一个域是<code>s_op</code>，它指向超级块的操作函数表。超级块函数表由<code>super_operations</code>结构体表示，定义在&lt;linux/fs.h&gt;中。该结构体中的每一项都是一个指向超级块操作函数的指针，超级块操作函数执行文件系统和索引节点的底层操作。</p>

      
    </div>
    
    
    

    
      <div>
        <div id="wechat_subscriber" style="display: block; padding: 10px 0; margin: 20px auto; width: 100%; text-align: center">
    <img id="wechat_subscriber_qcode" src="/images/wechat-qcode.jpg" alt="zxp wechat" style="width: 200px; max-width: 100%;"/>
    <div>欢迎关注微信公众号！</div>
</div>

      </div>
    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div></div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/images/WeChatpay.jpg" alt="zxp 微信支付"/>
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/images/Alipay.jpg" alt="zxp 支付宝"/>
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    
      <div>
        <ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者：</strong>
    zxp
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://zxpgo.github.io/2019/06/11/Linux内核阅读问题/" title="Linux内核分析">https://zxpgo.github.io/2019/06/11/Linux内核阅读问题/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>
    本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/" rel="external nofollow" target="_blank">CC BY-NC-SA 3.0</a> 许可协议。转载请注明出处！
  </li>
</ul>

      </div>
    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tag/Linux/" rel="tag"># Linux</a>
          
        </div>
      

      
      
        <div class="post-widgets">
        

        

        
          
          <div id="needsharebutton-postbottom">
            <span class="btn">
              <i class="fa fa-share-alt" aria-hidden="true"></i>
            </span>
          </div>
        
        </div>
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/05/20/STL学习/" rel="next" title="标准模板库STL">
                <i class="fa fa-chevron-left"></i> 标准模板库STL
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/06/14/面试常考题/" rel="prev" title="面试常考问题">
                面试常考问题 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
      <div id="lv-container" data-id="city" data-uid="MTAyMC8zODgxNC8xNTM0Mg=="></div>
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/images/avatar.gif"
                alt="zxp" />
            
              <p class="site-author-name" itemprop="name">zxp</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">176</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">16</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">48</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://blog.csdn.net/qq_25774883" target="_blank" title="CSDN">
                      
                        <i class="fa fa-fw fa-globe"></i>CSDN</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/zxpgo/zxpgo" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-globe"></i>GitHub</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://www.linkedin.com/feed/" target="_blank" title="LinkedIn">
                      
                        <i class="fa fa-fw fa-globe"></i>LinkedIn</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="1165772354@qq.com" target="_blank" title="E-Mail">
                      
                        <i class="fa fa-fw fa-envelope"></i>E-Mail</a>
                  </span>
                
            </div>
          

          
          

          
          
            <div class="links-of-blogroll motion-element links-of-blogroll-inline">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-link"></i>
                友情链接
              </div>
              <ul class="links-of-blogroll-list">
                
                  <li class="links-of-blogroll-item">
                    <a href="http://theme-next.iissnan.com" title="Next主题" target="_blank">Next主题</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://blog.rexking6.top" title="青爷博客" target="_blank">青爷博客</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://me.csdn.net/download/qq_25774883" title="CSDN下载" target="_blank">CSDN下载</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.livere.com/" title="来必力" target="_blank">来必力</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://tongji.baidu.com/web/welcome/login" title="百度统计" target="_blank">百度统计</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://leancloud.cn/" title="LeanCloud" target="_blank">LeanCloud</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://ibruce.info/2015/04/04/busuanzi/" title="不蒜子" target="_blank">不蒜子</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://leetcode-cn.com/" title="LeetCode" target="_blank">LeetCode</a>
                  </li>
                
              </ul>
            </div>
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#内核开发特点"><span class="nav-number">1.</span> <span class="nav-text">内核开发特点</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#无libc库或无标准头文件"><span class="nav-number">1.1.</span> <span class="nav-text">无libc库或无标准头文件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#GNU-C"><span class="nav-number">1.2.</span> <span class="nav-text">GNU C</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#内有内存保护机制"><span class="nav-number">1.3.</span> <span class="nav-text">内有内存保护机制</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#不要轻易在内核中使用浮点数"><span class="nav-number">1.4.</span> <span class="nav-text">不要轻易在内核中使用浮点数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#容积小而固定的栈"><span class="nav-number">1.5.</span> <span class="nav-text">容积小而固定的栈</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#同步和并发"><span class="nav-number">1.6.</span> <span class="nav-text">同步和并发</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#可移植性的重要性"><span class="nav-number">1.7.</span> <span class="nav-text">可移植性的重要性</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-进程管理"><span class="nav-number">2.</span> <span class="nav-text">2 进程管理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-进程"><span class="nav-number">2.1.</span> <span class="nav-text">2.1 进程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-进程描述符及任务结构"><span class="nav-number">2.2.</span> <span class="nav-text">2.2 进程描述符及任务结构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-进程的创建"><span class="nav-number">2.3.</span> <span class="nav-text">2.3 进程的创建</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-4-线程再Linux中的实现"><span class="nav-number">2.4.</span> <span class="nav-text">2.4 线程再Linux中的实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-5-进程终结"><span class="nav-number">2.5.</span> <span class="nav-text">2.5 进程终结</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#13-虚拟文件系统"><span class="nav-number">3.</span> <span class="nav-text">13 虚拟文件系统</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#VFS对象及其数据结构"><span class="nav-number">3.1.</span> <span class="nav-text">VFS对象及其数据结构</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div>
<script async src="https//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<i class="fa fa-user-md"></i><span id="busuanzi_container_site_pv" style='display:none'>
    本站总访问量 <span id="busuanzi_value_site_pv"></span> 
    <span class="post-meta-divider">|</span>
</span>
<span id="busuanzi_container_site_uv" style='display:none'>
    访问人数 <span id="busuanzi_value_site_uv"></span>
</span>
</div>


<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

<div class="copyright">&copy; 2018-8 &mdash; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-"></i> Power by 
  </span>
  <span class="author" itemprop="copyrightHolder">zxp</span>
  
  
</div>









        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    
      <div id="needsharebutton-float">
        <span class="btn">
          <i class="fa fa-share-alt" aria-hidden="true"></i>
        </span>
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  




  
  <div id="lv-container" data-uid="MTAyMC8zODgxNC8xNTM0Mg==">
    <script type="text/javascript">
      (function(d, s) {
        var j, e = d.getElementsByTagName(s)[0];
        if (typeof LivereTower === 'function') { return; }
        j = d.createElement(s);
        j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
        j.async = true;
        e.parentNode.insertBefore(j, e);
      })(document, 'script');
    </script>
	</div>
  











  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>
  <script>AV.initialize("2AyV3DKioBSdoryrFLRohzjB-gzGzoHsz", "XynedcHyJCVCrTfbD4yYnodo");</script>
  <script>
    function showTime(Counter) {
      var query = new AV.Query(Counter);
      var entries = [];
      var $visitors = $(".leancloud_visitors");

      $visitors.each(function () {
        entries.push( $(this).attr("id").trim() );
      });

      query.containedIn('url', entries);
      query.find()
        .done(function (results) {
          var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

          if (results.length === 0) {
            $visitors.find(COUNT_CONTAINER_REF).text(0);
            return;
          }

          for (var i = 0; i < results.length; i++) {
            var item = results[i];
            var url = item.get('url');
            var time = item.get('time');
            var element = document.getElementById(url);

            $(element).find(COUNT_CONTAINER_REF).text(time);
          }
          for(var i = 0; i < entries.length; i++) {
            var url = entries[i];
            var element = document.getElementById(url);
            var countSpan = $(element).find(COUNT_CONTAINER_REF);
            if( countSpan.text() == '') {
              countSpan.text(0);
            }
          }
        })
        .fail(function (object, error) {
          console.log("Error: " + error.code + " " + error.message);
        });
    }

    function addCount(Counter) {
      var $visitors = $(".leancloud_visitors");
      var url = $visitors.attr('id').trim();
      var title = $visitors.attr('data-flag-title').trim();
      var query = new AV.Query(Counter);

      query.equalTo("url", url);
      query.find({
        success: function(results) {
          if (results.length > 0) {
            var counter = results[0];
            counter.fetchWhenSave(true);
            counter.increment("time");
            counter.save(null, {
              success: function(counter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(counter.get('time'));
              },
              error: function(counter, error) {
                console.log('Failed to save Visitor num, with error message: ' + error.message);
              }
            });
          } else {
            var newcounter = new Counter();
            /* Set ACL */
            var acl = new AV.ACL();
            acl.setPublicReadAccess(true);
            acl.setPublicWriteAccess(true);
            newcounter.setACL(acl);
            /* End Set ACL */
            newcounter.set("title", title);
            newcounter.set("url", url);
            newcounter.set("time", 1);
            newcounter.save(null, {
              success: function(newcounter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(newcounter.get('time'));
              },
              error: function(newcounter, error) {
                console.log('Failed to create');
              }
            });
          }
        },
        error: function(error) {
          console.log('Error:' + error.code + " " + error.message);
        }
      });
    }

    $(function() {
      var Counter = AV.Object.extend("Counter");
      if ($('.leancloud_visitors').length == 1) {
        addCount(Counter);
      } else if ($('.post-title-link').length > 1) {
        showTime(Counter);
      }
    });
  </script>



  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  
  
  
  <link rel="stylesheet" href="/lib/needsharebutton/needsharebutton.css">

  
  
  <script src="/lib/needsharebutton/needsharebutton.js"></script>

  <script>
    
      pbOptions = {};
      
          pbOptions.iconStyle = "default";
      
          pbOptions.boxForm = "vertical";
      
          pbOptions.position = "top";
      
          pbOptions.networks = "Weibo,Wechat,Douban,QQZone,Twitter,Facebook";
      
      new needShareButton('#needsharebutton-postbottom', pbOptions);
    
    
      flOptions = {};
      
          flOptions.iconStyle = "box";
      
          flOptions.boxForm = "horizontal";
      
          flOptions.position = "middleRight";
      
          flOptions.networks = "Weibo,Wechat,Douban,QQZone,Twitter,Facebook";
      
      new needShareButton('#needsharebutton-float', flOptions);
    
  </script>

  

  
  
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script type="text/javascript" src="//cdn.bootcss.com/mathjax/2.7.1/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
  


  
  <script type="text/javascript" src="/js/src/js.cookie.js?v=5.1.4"></script>
  <script type="text/javascript" src="/js/src/scroll-cookie.js?v=5.1.4"></script>


  
  <script type="text/javascript" src="/js/src/exturl.js?v=5.1.4"></script>


  
  
  	 <!-- custom analytics part create by xiamo -->
<script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script>
<script>AV.initialize("2AyV3DKioBSdoryrFLRohzjB-gzGzoHsz", "XynedcHyJCVCrTfbD4yYnodo");</script>
<script>
function showTime(Counter) {
	var query = new AV.Query(Counter);
	$(".leancloud_visitors").each(function() {
		var url = $(this).attr("id").trim();
		query.equalTo("url", url);
		query.find({
			success: function(results) {
				if (results.length == 0) {
					var content = $(document.getElementById(url)).text() + ' 0';
					$(document.getElementById(url)).text(content);
					return;
				}
				for (var i = 0; i < results.length; i++) {
					var object = results[i];
					var content = $(document.getElementById(url)).text() + ' ' + object.get('time');
					$(document.getElementById(url)).text(content);
				}
			}
		});

	});
}

</script>
  
</body>
</html>
